<?php

namespace Xin\HttpClient;

use GuzzleHttp\Cookie\CookieJarInterface;
use Xin\Support\Arr;
use Xin\Support\Reflect;

trait OperationConfigures
{
	/**
	 * 获取配置
	 * @param string|null $key
	 * @return array|\ArrayAccess|mixed
	 * @noinspection PhpDocMissingThrowsInspection
	 */
	public function getOptions($key = null)
	{
		$options = Reflect::get($this->client, 'config');

		if ($key) {
			return Arr::get($options, $key);
		}

		return $options;
	}

	/**
	 * 合并配置
	 * @param array $options
	 * @return $this
	 * @noinspection PhpDocMissingThrowsInspection
	 */
	public function mergeOptions(array $options = [])
	{
		$defaultOptions = $this->getOptions();

		return $this->setOptions(array_replace_recursive($defaultOptions, $options));
	}

	/**
	 * 设置新的配置
	 * @param array $options
	 * @noinspection PhpDocMissingThrowsInspection
	 * @return $this
	 */
	public function setOptions(array $options)
	{
		/** @noinspection PhpUnhandledExceptionInspection */
		Reflect::call($this->client, 'configureDefaults', [$options], true);

		return $this;
	}

	/**
	 * 设置配置
	 * @param string $key
	 * @param mixed $value
	 * @return $this
	 * @noinspection PhpDocMissingThrowsInspection
	 */
	protected function setOption($key, $value)
	{
		/** @noinspection PhpUnhandledExceptionInspection */
		Reflect::set($this->client, 'config', function ($config) use ($key, $value) {
			Arr::set($config, $key, $value);
			return $config;
		});

		return $this;
	}

	/**
	 * 移除配置
	 * @param string $key
	 * @return $this
	 * @noinspection PhpDocMissingThrowsInspection
	 */
	protected function removeOption($key)
	{
		Reflect::set($this->client, 'config', function ($config) use ($key) {
			Arr::forget($config, $key);
			return $config;
		});

		return $this;
	}

	/**
	 * 设置是否使用 XMLHttpRequest
	 * @param bool $enable
	 * @return $this
	 */
	public function withXMLHttpRequest($enable = true)
	{
		if ($enable) {
			$this->setOption('headers.X-Requested-With', 'XMLHttpRequest');
		} else {
			$this->removeOption('headers.X-Requested-With');
		}

		return $this;
	}

	/**
	 * 设置 Content-Type 为 application/json
	 * @return $this
	 */
	public function withContentTypeAsJson()
	{
		$this->setOption('headers.Content-Type', 'application/json');
		return $this;
	}

	/**
	 * 设置 Content-Type 为 application/xml
	 * @return $this
	 */
	public function withContentTypeAsXml()
	{
		$this->setOption('headers.Content-Type', 'application/xml');
		return $this;
	}

	/**
	 * 设置 Content-Type 为 application/x-www-form-urlencoded
	 * @return $this
	 */
	public function withContentTypeFormUrlEncoded()
	{
		$this->setOption('headers.Content-Type', 'application/x-www-form-urlencoded');
		return $this;
	}

	/**
	 * 设置 Content-Type 为 multipart/form-data
	 * @return $this
	 */
	public function withContentTypeAsMultipartFormData()
	{
		$this->setOption('headers.Content-Type', 'multipart/form-data');
		return $this;
	}

	/**
	 * 设置 Content-Type 为 text/plain
	 * @return $this
	 */
	public function withContentTypeAsText()
	{
		$this->setOption('headers.Content-Type', 'text/plain');
		return $this;
	}

	/**
	 * 设置 Accept 为 application/json
	 * @return $this
	 */
	public function withAcceptAsJson()
	{
		$this->setOption('headers.Accept', 'application/json');

		return $this;
	}

	/**
	 * 设置 Accept 为 text/plain
	 * @return $this
	 */
	public function withAcceptAsText()
	{
		$this->setOption('headers.Accept', 'text/plain');

		return $this;
	}

	/**
	 * 设置 Accept 为 application/xml
	 * @return $this
	 */
	public function withAcceptAsXml()
	{
		$this->setOption('headers.Accept', 'application/xml');

		return $this;
	}

	/**
	 * 设置 Accept 为 text/html
	 * @return $this
	 */
	public function withAcceptAsHtml()
	{
		$this->setOption('headers.Accept', 'text/html');

		return $this;
	}

	/**
	 * 移除 Accept
	 * @return $this
	 */
	public function removeAccept()
	{
		$this->removeOption('headers.Accept');

		return $this;
	}

	/**
	 * 获取 CookieJar
	 * @return CookieJarInterface
	 */
	public function cookieJar()
	{
		return $this->getOptions('cookies');
	}

	/**
	 * 设置 CookieJar
	 * @param CookieJarInterface|null $cookieJar
	 * @return $this
	 */
	public function withCookieJar(CookieJarInterface $cookieJar = null)
	{
		$this->setOption('cookies', $cookieJar);

		return $this;
	}
}
